package com.shark.lib.rebirth;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Messenger;
import android.util.Log;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;


public class WatchDogService extends Service {
    private static final String TAG = "RebirthWatchService";
    private SeviceCancelBroadcastReceiver broadcastReceiver;
    protected static final int HASH_CODE = 20200417;
    protected static Disposable mDisposable;
    protected static PendingIntent mPendingIntent;

    private boolean needStartDaemon;

    private AbsServiceConnection mConnection = new AbsServiceConnection() {
        @Override
        public void onDisconnected(ComponentName name) {
            startBindWorkServices();
        }
    };

    private void startBindWorkServices() {
        if (needStartDaemon) {
            Log.e(TAG, "启动工作进程服务... ");
            RebirthEnv.bindDaemonService(this, mConnection);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new Messenger(new Handler()).getBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        needStartDaemon = RebirthEnv.needStartDaemon(this);
        if (!needStartDaemon) {
            stopSelf();
            return;
        }
        startRegisterReceiver();
        ForegroundNotificationUtils.startForegroundNotification(this);
        //守护 Service 组件的启用状态, 使其不被 MAT 等工具禁用
        getPackageManager().setComponentEnabledSetting(new ComponentName(getPackageName(), RebirthService.class.getName()),
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart();
        return START_STICKY;
    }

    private void onStart() {
        if (mDisposable == null || mDisposable.isDisposed()) {
            //定时检查 AbsWorkService 是否在运行，如果不在运行就把它拉起来   Android 5.0+ 使用 JobScheduler，效果比 AlarmManager 好
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                JobInfo.Builder builder = new JobInfo.Builder(HASH_CODE,
                        new ComponentName(WatchDogService.this, JobSchedulerService.class));
                builder.setPeriodic(RebirthEnv.getWakeUpInterval(RebirthEnv.MINIMAL_WAKE_UP_INTERVAL));
                //Android 7.0+ 增加了一项针对 JobScheduler 的新限制，最小间隔只能是下面设定的数字
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    builder.setPeriodic(JobInfo.getMinPeriodMillis(), JobInfo.getMinFlexMillis());
                }
                builder.setPersisted(true);
                JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
                scheduler.schedule(builder.build());
            } else {
                //Android 4.4- 使用 AlarmManager
                AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
                Intent i = new Intent(WatchDogService.this, RebirthEnv.client.mConfigurations.PERSISTENT_CONFIG.serviceClass);
                mPendingIntent = PendingIntent.getService(WatchDogService.this, HASH_CODE, i, PendingIntent.FLAG_UPDATE_CURRENT);
                am.setRepeating(AlarmManager.RTC_WAKEUP,
                        System.currentTimeMillis() + RebirthEnv.getWakeUpInterval(RebirthEnv.MINIMAL_WAKE_UP_INTERVAL),
                        RebirthEnv.getWakeUpInterval(RebirthEnv.MINIMAL_WAKE_UP_INTERVAL), mPendingIntent);
            }
            //使用定时 Observable，避免 Android 定制系统 JobScheduler / AlarmManager 唤醒间隔不稳定的情况
            mDisposable = Observable
                    .interval(RebirthEnv.getWakeUpInterval(RebirthEnv.MINIMAL_WAKE_UP_INTERVAL), TimeUnit.MILLISECONDS)
                    .subscribe(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            startBindWorkServices();
                        }
                    });
            startBindWorkServices();
        }
    }

    private void onEnd() {
        startBindWorkServices();
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        onEnd();
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy... ");
        onEnd();
        stopRegisterReceiver();
        ForegroundNotificationUtils.deleteForegroundNotification(this);
    }

    private void stopService() {
        needStartDaemon = false;
        stopDaemonWork();
        RebirthEnv.safelyUnbindService(this, mConnection);
        stopSelf();
    }

    private void stopDaemonWork() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            JobScheduler scheduler = (JobScheduler) WatchDogService.this.getSystemService(JOB_SCHEDULER_SERVICE);
            scheduler.cancel(HASH_CODE);
        } else {
            AlarmManager am = (AlarmManager) WatchDogService.this.getSystemService(ALARM_SERVICE);
            if (mPendingIntent != null) {
                am.cancel(mPendingIntent);
            }
        }
        if (mDisposable != null && !mDisposable.isDisposed()) {
            mDisposable.dispose();
        }
    }


    private void startRegisterReceiver() {
        if (broadcastReceiver == null) {
            broadcastReceiver = new SeviceCancelBroadcastReceiver();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(RebirthEnv.ACTION_CANCEL_JOB_ALARM_SUB);
            registerReceiver(broadcastReceiver, intentFilter);
        }
    }

    private void stopRegisterReceiver() {
        if (broadcastReceiver != null) {
            unregisterReceiver(broadcastReceiver);
            broadcastReceiver = null;
        }
    }

    class SeviceCancelBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            stopService();
        }
    }
}
